
package nxu.it;

import freemarker.template.Template;
import freemarker.template.TemplateException;
import io.quarkiverse.freemarker.TemplatePath;
import io.smallrye.common.annotation.Blocking;
import io.smallrye.mutiny.Uni;
import io.vertx.core.impl.NoStackTraceTimeoutException;
import jakarta.enterprise.context.RequestScoped;
import jakarta.inject.Inject;
import jakarta.ws.rs.GET;
import jakarta.ws.rs.POST;
import jakarta.ws.rs.Path;
import jakarta.ws.rs.Produces;
import jakarta.ws.rs.core.MediaType;
import org.eclipse.microprofile.rest.client.inject.RestClient;
import org.jboss.resteasy.reactive.RestResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.io.StringWriter;
import java.net.http.HttpConnectTimeoutException;
import java.time.Duration;
import java.time.temporal.ChronoUnit;
import java.util.List;
import java.util.Map;

@RequestScoped
@Path("/")
public class SignResource {

    private static final Logger LOG = LoggerFactory.getLogger(SignResource.class);

    @Inject
    @TemplatePath("index.ftl")
    Template indexTpl;

    @Inject
    @TemplatePath("list.ftl")
    Template listTpl;

    @Inject
    TokenService tokenService;

    @RestClient
    RemoteSignClient remoteSignClient;


    @Path("/")
    @GET
    @Produces(MediaType.TEXT_HTML)
    public String index() throws TemplateException, IOException {
        StringWriter stringWriter = new StringWriter();
        indexTpl.process(Map.of(), stringWriter);
        return stringWriter.toString();

    }

    @Path("/list")
    @GET
    @Produces(MediaType.TEXT_HTML)
    public String list() throws TemplateException, IOException {
        StringWriter stringWriter = new StringWriter();
        listTpl.process(Map.of(), stringWriter);
        return stringWriter.toString();
    }

    @Path("/sign")
    @POST
    public Uni<RestResponse<SignResult>> sign(SignRequest signRequest) {
        return remoteSignClient.sign(tokenService.generateToken(), signRequest)
                .onFailure(Exception.class)
                .retry()
                .withBackOff(Duration.ofSeconds(2), Duration.ofSeconds(5))
                .atMost(2)
                .onFailure().invoke(ex -> LOG.error("远程调用签到失败,原因:{}", ex.getMessage()))
                .onFailure().recoverWithNull()
                .onItemOrFailure()
                .transform((item, ex) -> {
                    if (item == null) {
                        item = new SignResult();
                    }

                    return RestResponse.ResponseBuilder.ok(item).build();
                });

    }


    @POST
    @Path("/sign/list")
    public Uni<RestResponse<List<UserDto>>> signList() {
        return remoteSignClient.list(tokenService.generateToken())
                .onFailure(Exception.class)
                .retry()
                .withBackOff(Duration.ofSeconds(2), Duration.ofSeconds(5))
                .atMost(2)
                .onFailure().invoke(ex -> LOG.error("远程调用获取签到名单失败,原因:{}", ex.getMessage()))
                .onFailure().recoverWithNull()
                .onItemOrFailure()
                .transform((item, ex) -> {
                    if (item == null) {
                        item = List.of();
                    }

                    return RestResponse.ResponseBuilder.ok(item).build();
                });
    }
}

